// react 文件上传组件
import React, { Component } from 'react';
import axios from 'axios';
import './index.css';

class Upload extends Component {
    constructor(props) {
        super(props);
        this.state = {
            uploadChunkList: [],
            uploadFile: null,
        };
    }

    // 监听文件上传
    handleFileChange = (e) => {
        // 获取文件对象
        const file = e.target.files[0];
        console.log(file);
        // 获取文件名
        const fileName = file.name;
        console.log("fileName", fileName);
        // 获取文件大小
        const fileSize = (file.size / (1024 * 1024)).toFixed(2);
        console.log(fileSize + 'MB');

        this.setState({ uploadFile: file });
    }

    // 上传文件回调函数
    handleUpload = () => {
        const { uploadFile } = this.state;
        // console.log(uploadFile);

        // 判断文件是否选择并且非空
        if (!uploadFile) {
            return alert('请选择文件');
        }

        // 创建切片
        const chunkList = this.createChunk(uploadFile);
        // console.log(chunkList);

        // 另外切片需要打上标记，保证后端正确合并
        const uploadChunkList = chunkList.map((file, index) => {
            return {
                file,
                size: file.size,
                percent: 0,
                chunkName: `${uploadFile.name}-${index}`,
                fileName: uploadFile.name,
                index,
            };
        });

        this.setState({ uploadChunkList }, () => {
            console.log(this.state.uploadChunkList);
            // 发请求 把切片一个一个地给后端
            // this.uploadChunks();
        });
    }

    // 创建切片
    createChunk = (file) => {
        const chunkSize = 1024 * 1024; // 每个切片的大小为1MB
        let chunks = [];  // 切片数组
        let start = 0;  // 切片开始位置
        let end = chunkSize;  // 切片结束位置

        while (start < file.size) {
            chunks.push(file.slice(start, end));
            start = end;
            end += chunkSize;
        }

        return chunks;
    }

    // 上传切片
    uploadChunks = async () => {
        const { uploadChunkList } = this.state;

        for (let i = 0; i < uploadChunkList.length; i++) {
            const chunk = uploadChunkList[i];

            try {
                await this.requestUpload({
                    url: '/api/upload', // 替换为实际的上传接口地址
                    method: 'post',
                    data: chunk.file,
                    headers: {
                        'Content-Type': 'application/octet-stream',
                        'X-Chunk-Name': chunk.chunkName,
                        'X-File-Name': chunk.fileName,
                        'X-Chunk-Index': chunk.index,
                    },
                    onUploadProgress: (progressEvent) => {
                        const percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total);
                        this.updateChunkProgress(i, percentCompleted);
                    },
                });
                console.log(`Chunk ${i + 1} uploaded successfully`);
            } catch (error) {
                console.error(`Error uploading chunk ${i + 1}:`, error);
                alert('文件上传失败，请重试');
                break; // 停止上传剩余的切片
            }
        }
    }

    // 更新切片上传进度
    updateChunkProgress = (index, percent) => {
        const { uploadChunkList } = this.state;
        const updatedChunkList = uploadChunkList.map((chunk, i) => {
            if (i === index) {
                return {
                    ...chunk,
                    percent,
                };
            }
            return chunk;
        });

        this.setState({ uploadChunkList: updatedChunkList });
    }

    requestUpload = ({ url, method = 'post', data, headers = {}, onUploadProgress = (e) => e }) => {
        return new Promise((resolve, reject) => {
            // axios支持在请求中传入一个回调onUploadProgress，其目的就是为了知道请求的进度
            axios[method](url, data, { headers, onUploadProgress })
                .then(res => {
                    resolve(res);
                })
                .catch(err => {
                    reject(err);
                });
        });
    }

    render() {
        return (
            // 上传文件
            <div className='upload-container'>
                <input type="file" ref={(ref) => this.fileInput = ref} onChange={this.handleFileChange} />
                <button onClick={this.handleUpload}>上传</button>
            </div>
        );
    }
}

export default Upload;